using System;
using System.Collections.Generic;
using System.Text;

namespace SP.Parameter
{
    /// <summary>
    /// A generic vector parameter.
    /// </summary>
    public class VectorParamter : IParameter
    {
        public VectorParamter(string name, int size)
        {
            mName = name;
            mVec = new float[size];
        }

        private string mName;
        public string Name
        {
            get { return mName; }
        }

        private string mDesc;
        public string Desc
        {
            get { return mDesc; }
        }

        private float[] mVec;
        public string Value
        {
            get { return ToString(); }
            set { FromString(value); }
        }

        private bool mEditable = true;
        public bool Editable
        {
            get { return mEditable; }
            set { mEditable = value; }
        }

        public float[] Vec
        {
            get { return mVec; }
        }

        public string UserData;

        public VectorParamter SetDesc(string desc)
        {
            mDesc = desc;
            return this;
        }

        public VectorParamter SetEditable(bool val)
        {
            mEditable = val;
            return this;
        }

        public VectorParamter SetUserData(string val)
        {
            UserData = val;
            return this;
        }

        public override string ToString()
        {
            switch (mVec.Length)
            {
                case 1:
                    return mVec[0].ToString();

                case 2:
                    return String.Format("{0}, {1}", mVec[0], mVec[1]);

                case 3:
                    return String.Format("{0}, {1}, {2}", mVec[0], mVec[1], mVec[2]);

                case 4:
                    return String.Format("{0}, {1}, {2}, {3}", mVec[0], mVec[1], mVec[2], mVec[3]);

                default:
                    return mVec.ToString();
            }
        }

        public void FromString(string str)
        {
            string[] t = str.Split(new char[] { ',' });

            foreach (string s in t)
            {
                float f;
                if (!float.TryParse(s, out f))
                {
                    return;
                }
            }

            for (int i = 0; i < t.Length && i < mVec.Length; ++i)
            {
                mVec[i] = float.Parse(t[i]);
            }
        }
    }

    /// <summary>
    /// A scalar
    /// </summary>
    public class ScalarParameter : VectorParamter
    {
        public ScalarParameter(string name)
            : base(name, 1)
        {
        }

        public float s
        {
            get { return Vec[0]; }
            set { Vec[0] = value; }
        }

        public ScalarParameter SetS(float val)
        {
            s = val;
            return this;
        }
    }

    /// <summary>
    /// A 2d-vector paramater
    /// </summary>
    public class Vec2Parameter : VectorParamter
    {
        public Vec2Parameter(string name)
            : base(name, 2)
        {
        }

        public float x
        {
            get { return Vec[0]; }
            set { Vec[0] = value; }
        }

        public float y
        {
            get { return Vec[1]; }
            set { Vec[1] = value; }
        }

        public Vec2Parameter SetX(float val)
        {
            x = val;
            return this;
        }

        public Vec2Parameter SetY(float val)
        {
            y = val;
            return this;
        }
    }

    /// <summary>
    /// A 3d-vector paramater
    /// </summary>
    public class Vec3Parameter : VectorParamter
    {
        public Vec3Parameter(string name)
            : base(name, 3)
        {
        }

        public float x
        {
            get { return Vec[0]; }
            set { Vec[0] = value; }
        }

        public float y
        {
            get { return Vec[1]; }
            set { Vec[1] = value; }
        }

        public float z
        {
            get { return Vec[2]; }
            set { Vec[2] = value; }
        }

        public Vec3Parameter SetX(float val)
        {
            x = val;
            return this;
        }

        public Vec3Parameter SetY(float val)
        {
            y = val;
            return this;
        }

        public Vec3Parameter SetZ(float val)
        {
            z = val;
            return this;
        }
    }

    /// <summary>
    /// A 3d-vector paramater
    /// </summary>
    public class Vec4Parameter : VectorParamter
    {
        public Vec4Parameter(string name)
            : base(name, 4)
        {
        }

        public float x
        {
            get { return Vec[0]; }
            set { Vec[0] = value; }
        }

        public float y
        {
            get { return Vec[1]; }
            set { Vec[1] = value; }
        }

        public float z
        {
            get { return Vec[2]; }
            set { Vec[2] = value; }
        }

        public float w
        {
            get { return Vec[3]; }
            set { Vec[3] = value; }
        }

        public Vec4Parameter SetX(float val)
        {
            x = val;
            return this;
        }

        public Vec4Parameter SetY(float val)
        {
            y = val;
            return this;
        }

        public Vec4Parameter SetZ(float val)
        {
            z = val;
            return this;
        }

        public Vec4Parameter SetW(float val)
        {
            w = val;
            return this;
        }
    }

    /// <summary>
    /// A color paramater
    /// </summary>
    public class ColorParameter : VectorParamter
    {
        public ColorParameter(string name)
            : base(name, 4)
        {
        }

        public float r
        {
            get { return Vec[0]; }
            set { Vec[0] = value; }
        }

        public float g
        {
            get { return Vec[1]; }
            set { Vec[1] = value; }
        }

        public float b
        {
            get { return Vec[2]; }
            set { Vec[2] = value; }
        }

        public float a
        {
            get { return Vec[3]; }
            set { Vec[3] = value; }
        }

        public ColorParameter SetR(float val)
        {
            r = val;
            return this;
        }

        public ColorParameter SetG(float val)
        {
            g = val;
            return this;
        }

        public ColorParameter SetB(float val)
        {
            b = val;
            return this;
        }

        public ColorParameter SetA(float val)
        {
            a = val;
            return this;
        }
    }
}
